package com.yyw.foodie.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.yyw.foodie.bo.cart.ShopCartBo;
import com.yyw.foodie.mapper.ItemsMapper;
import com.yyw.foodie.pojo.ItemsEntity;
import com.yyw.foodie.pojo.ItemsImgEntity;
import com.yyw.foodie.pojo.ItemsParamEntity;
import com.yyw.foodie.pojo.ItemsSpecEntity;
import com.yyw.foodie.service.ItemsImgService;
import com.yyw.foodie.service.ItemsParamService;
import com.yyw.foodie.service.ItemsService;
import com.yyw.foodie.service.ItemsSpecService;
import com.yyw.foodie.utils.PagedGridResult;
import com.yyw.foodie.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

/**
 * <p>
 * 商品表 商品信息相关表：分类表，商品图片表，商品规格表，商品参数表 服务实现类
 * </p>
 *
 * @author yiyw
 * @since 2021-05-22
 */
@Service
@Slf4j
public class ItemsServiceImpl extends ServiceImpl<ItemsMapper, ItemsEntity> implements ItemsService {

    @Autowired
    private ThreadPoolExecutor poolExecutor;

    @Autowired
    private ItemsImgService itemsImgService;

    @Autowired
    private ItemsSpecService itemsSpecService;

    @Autowired
    private ItemsParamService itemsParamService;

    @Autowired
    private ItemsMapper itemsMapper;

    /**
     * 获取商品详情页的商品信息
     *
     * @param itemId 商品ID
     * @return
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @Override
    @Transactional(propagation = Propagation.SUPPORTS)
    public ItemsDetailsVo getItemsInfo(String itemId) throws ExecutionException, InterruptedException {
        // 1. 获取商品基本信息
        CompletableFuture<ItemInfoVo> itemsInfo = CompletableFuture.supplyAsync(() -> {
            log.info("线程--{} 开始并行获取商品信息", Thread.currentThread().getName());
            ItemsEntity itemsEntity = getById(itemId);
            ItemInfoVo infoVo = new ItemInfoVo();
            BeanUtils.copyProperties(itemsEntity, infoVo);
            return infoVo;
        }, poolExecutor).exceptionally(e -> {
            log.error("获取商品信息发生了异常..", e.getMessage());
            return null;
        });

        // 2. 获取商品图片信息
        CompletableFuture<List<?>> imgVo = CompletableFuture.supplyAsync(() -> {
            log.info("线程--{} 开始并行获取商品图片信息", Thread.currentThread().getName());
            QueryWrapper<ItemsImgEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(ItemsImgEntity::getItemId, itemId);
            List<ItemsImgEntity> list = itemsImgService.list(queryWrapper);
            if (CollectionUtils.isEmpty(list)) {
                return new ArrayList<>();
            }
            return list.stream().map(e -> {
                ItemsImgsVo imgsVo = new ItemsImgsVo();
                BeanUtils.copyProperties(e, imgsVo);
                return imgsVo;
            }).collect(Collectors.toList());
        }, poolExecutor).exceptionally(e -> {
            log.error("获取商品图片信息发生了异常..", e.getMessage());
            return new ArrayList<>();
        });

        // 3. 获取商品规格参数
        CompletableFuture<ItemsParamVo> paramVo = CompletableFuture.supplyAsync(() -> {
            log.info("线程--{} 开始并行获取商品图片信息", Thread.currentThread().getName());
            QueryWrapper<ItemsParamEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(ItemsParamEntity::getItemId, itemId);
            ItemsParamEntity one = itemsParamService.getOne(queryWrapper);
            ItemsParamVo vo = new ItemsParamVo();
            BeanUtils.copyProperties(one, vo);
            return vo;
        }, poolExecutor).exceptionally(e -> {
            log.error("获取商品规格参数发生了异常..", e.getMessage());
            return new ItemsParamVo();
        });

        // 4. 获取商品sku信息
        CompletableFuture<List<?>> skuVo = CompletableFuture.supplyAsync(() -> {
            log.info("线程--{} 开始并行获取商品SKU信息", Thread.currentThread().getName());
            QueryWrapper<ItemsSpecEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(ItemsSpecEntity::getItemId, itemId);
            List<ItemsSpecEntity> list = itemsSpecService.list(queryWrapper);
            if (CollectionUtils.isEmpty(list)) {
                return new ArrayList<>();
            }
            return list.stream().map(e -> {
                ItemsSpecVo vo = new ItemsSpecVo();
                BeanUtils.copyProperties(e, vo);
                return vo;
            }).collect(Collectors.toList());
        }, poolExecutor).exceptionally(e -> {
            log.error("获取商品SKU信息发生异常...", e.getMessage());
            return new ArrayList<>();
        });

        // 5. 组合任务
        CompletableFuture<Void> all = CompletableFuture.allOf(itemsInfo, imgVo, paramVo, skuVo);
        // 等待全部任务完成
        all.get();

        // 6. 获取结果
        ItemInfoVo infoVo = itemsInfo.get();
        List<ItemsImgsVo> imgVoList = (List<ItemsImgsVo>) imgVo.get();
        ItemsParamVo itemsParamVo = paramVo.get();
        List<ItemsSpecVo> skuVoList = (List<ItemsSpecVo>) skuVo.get();

        // 7. 组装数据
        ItemsDetailsVo detailsVo = new ItemsDetailsVo();
        detailsVo.setItem(infoVo);
        detailsVo.setItemImgList(imgVoList);
        detailsVo.setItemParams(itemsParamVo);
        detailsVo.setItemSpecList(skuVoList);

        return detailsVo;
    }

    @Override
    public PagedGridResult itemsPage(String keyWords, String sort, Integer page, Integer pageSize) {
        PageHelper.startPage(page, pageSize);
        List<SearchItemsVo> itemsVos = itemsMapper.searchItemByPage(keyWords, sort);
        PagedGridResult result = PagedGridResult.setterPagedGrid(itemsVos, page);
        return result;
    }

    @Override
    public PagedGridResult itemsPageByCategory(String catId, String sort, Integer page, Integer pageSize) {
        PageHelper.startPage(page, pageSize);
        List<SearchItemsVo> itemsVos = itemsMapper.searchItemByCategoryAndPage(Integer.parseInt(catId), sort);
        PagedGridResult result = PagedGridResult.setterPagedGrid(itemsVos, page);
        return result;
    }

    @Override
    public List<ShopCartBo> getItemsByCart(String[] skuIds) {
        List<ShopCartBo> list = itemsMapper.getNewItmesInfoByCart(skuIds);
        return list;
    }
}
